home *** CD-ROM | disk | FTP | other *** search
/ Chip 2007 January, February, March & April / Chip-Cover-CD-2007-02.iso / Pakiet bezpieczenstwa / mini Pentoo LiveCD 2006.1 / mpentoo-2006.1.iso / livecd.squashfs / usr / lib / python2.4 / compiler / pyassem.pyc (.txt) < prev    next >
Python Compiled Bytecode  |  2005-10-18  |  26KB  |  941 lines

  1. # Source Generated with Decompyle++
  2. # File: in.pyc (Python 2.4)
  3.  
  4. '''A flow graph representation for Python bytecode'''
  5. import dis
  6. import new
  7. import sys
  8. import types
  9. from compiler import misc
  10. from compiler.consts import CO_OPTIMIZED, CO_NEWLOCALS, CO_VARARGS, CO_VARKEYWORDS
  11.  
  12. class FlowGraph:
  13.     
  14.     def __init__(self):
  15.         self.current = self.entry = Block()
  16.         self.exit = Block('exit')
  17.         self.blocks = misc.Set()
  18.         self.blocks.add(self.entry)
  19.         self.blocks.add(self.exit)
  20.  
  21.     
  22.     def startBlock(self, block):
  23.         if self._debug:
  24.             if self.current:
  25.                 print 'end', repr(self.current)
  26.                 print '    next', self.current.next
  27.                 print '   ', self.current.get_children()
  28.             
  29.             print repr(block)
  30.         
  31.         self.current = block
  32.  
  33.     
  34.     def nextBlock(self, block = None):
  35.         if block is None:
  36.             block = self.newBlock()
  37.         
  38.         self.current.addNext(block)
  39.         self.startBlock(block)
  40.  
  41.     
  42.     def newBlock(self):
  43.         b = Block()
  44.         self.blocks.add(b)
  45.         return b
  46.  
  47.     
  48.     def startExitBlock(self):
  49.         self.startBlock(self.exit)
  50.  
  51.     _debug = 0
  52.     
  53.     def _enable_debug(self):
  54.         self._debug = 1
  55.  
  56.     
  57.     def _disable_debug(self):
  58.         self._debug = 0
  59.  
  60.     
  61.     def emit(self, *inst):
  62.         if self._debug:
  63.             print '\t', inst
  64.         
  65.         if inst[0] in [
  66.             'RETURN_VALUE',
  67.             'YIELD_VALUE']:
  68.             self.current.addOutEdge(self.exit)
  69.         
  70.         if len(inst) == 2 and isinstance(inst[1], Block):
  71.             self.current.addOutEdge(inst[1])
  72.         
  73.         self.current.emit(inst)
  74.  
  75.     
  76.     def getBlocksInOrder(self):
  77.         '''Return the blocks in reverse postorder
  78.  
  79.         i.e. each node appears before all of its successors
  80.         '''
  81.         for b in self.blocks.elements():
  82.             if b is self.exit:
  83.                 continue
  84.             
  85.             if not b.next:
  86.                 b.addNext(self.exit)
  87.                 continue
  88.         
  89.         order = dfs_postorder(self.entry, { })
  90.         order.reverse()
  91.         self.fixupOrder(order, self.exit)
  92.         if self.exit not in order:
  93.             order.append(self.exit)
  94.         
  95.         return order
  96.  
  97.     
  98.     def fixupOrder(self, blocks, default_next):
  99.         '''Fixup bad order introduced by DFS.'''
  100.         self.fixupOrderHonorNext(blocks, default_next)
  101.         self.fixupOrderForward(blocks, default_next)
  102.  
  103.     
  104.     def fixupOrderHonorNext(self, blocks, default_next):
  105.         '''Fix one problem with DFS.
  106.  
  107.         The DFS uses child block, but doesn\'t know about the special
  108.         "next" block.  As a result, the DFS can order blocks so that a
  109.         block isn\'t next to the right block for implicit control
  110.         transfers.
  111.         '''
  112.         index = { }
  113.         for i in range(len(blocks)):
  114.             index[blocks[i]] = i
  115.         
  116.         for i in range(0, len(blocks) - 1):
  117.             b = blocks[i]
  118.             n = blocks[i + 1]
  119.             if not (b.next) and b.next[0] == default_next or b.next[0] == n:
  120.                 continue
  121.             
  122.             cur = b
  123.             chain = []
  124.             elt = cur
  125.             while elt.next and elt.next[0] != default_next:
  126.                 chain.append(elt.next[0])
  127.                 elt = elt.next[0]
  128.             l = []
  129.             for b in chain:
  130.                 if not index[b] > i:
  131.                     raise AssertionError
  132.                 l.append((index[b], b))
  133.             
  134.             l.sort()
  135.             l.reverse()
  136.             for j, b in l:
  137.                 del blocks[index[b]]
  138.             
  139.             blocks[i:i + 1] = [
  140.                 cur] + chain
  141.             for i in range(len(blocks)):
  142.                 index[blocks[i]] = i
  143.             
  144.         
  145.  
  146.     
  147.     def fixupOrderForward(self, blocks, default_next):
  148.         '''Make sure all JUMP_FORWARDs jump forward'''
  149.         index = { }
  150.         chains = []
  151.         cur = []
  152.         for b in blocks:
  153.             index[b] = len(chains)
  154.             cur.append(b)
  155.             if b.next and b.next[0] == default_next:
  156.                 chains.append(cur)
  157.                 cur = []
  158.                 continue
  159.         
  160.         chains.append(cur)
  161.         while None:
  162.             constraints = []
  163.             for i in range(len(chains)):
  164.                 l = chains[i]
  165.                 for b in l:
  166.                     for c in b.get_children():
  167.                         if index[c] < i:
  168.                             forward_p = 0
  169.                             for inst in b.insts:
  170.                                 if inst[0] == 'JUMP_FORWARD':
  171.                                     if inst[1] == c:
  172.                                         forward_p = 1
  173.                                     
  174.                                 inst[1] == c
  175.                             
  176.                             if not forward_p:
  177.                                 continue
  178.                             
  179.                             constraints.append((index[c], i))
  180.                             continue
  181.                     
  182.                 
  183.             
  184.             if not constraints:
  185.                 break
  186.             
  187.             (goes_before, a_chain) = constraints[0]
  188.             if not a_chain > goes_before:
  189.                 raise AssertionError
  190.             c = chains[a_chain]
  191.             chains.remove(c)
  192.             chains.insert(goes_before, c)
  193.         del blocks[:]
  194.         for c in chains:
  195.             for b in c:
  196.                 blocks.append(b)
  197.             
  198.         
  199.  
  200.     
  201.     def getBlocks(self):
  202.         return self.blocks.elements()
  203.  
  204.     
  205.     def getRoot(self):
  206.         '''Return nodes appropriate for use with dominator'''
  207.         return self.entry
  208.  
  209.     
  210.     def getContainedGraphs(self):
  211.         l = []
  212.         for b in self.getBlocks():
  213.             l.extend(b.getContainedGraphs())
  214.         
  215.         return l
  216.  
  217.  
  218.  
  219. def dfs_postorder(b, seen):
  220.     '''Depth-first search of tree rooted at b, return in postorder'''
  221.     order = []
  222.     seen[b] = b
  223.     for c in b.get_children():
  224.         if seen.has_key(c):
  225.             continue
  226.         
  227.         order = order + dfs_postorder(c, seen)
  228.     
  229.     order.append(b)
  230.     return order
  231.  
  232.  
  233. class Block:
  234.     _count = 0
  235.     
  236.     def __init__(self, label = ''):
  237.         self.insts = []
  238.         self.inEdges = misc.Set()
  239.         self.outEdges = misc.Set()
  240.         self.label = label
  241.         self.bid = Block._count
  242.         self.next = []
  243.         Block._count = Block._count + 1
  244.  
  245.     
  246.     def __repr__(self):
  247.         if self.label:
  248.             return '<block %s id=%d>' % (self.label, self.bid)
  249.         else:
  250.             return '<block id=%d>' % self.bid
  251.  
  252.     
  253.     def __str__(self):
  254.         insts = map(str, self.insts)
  255.         return '<block %s %d:\n%s>' % (self.label, self.bid, '\n'.join(insts))
  256.  
  257.     
  258.     def emit(self, inst):
  259.         op = inst[0]
  260.         if op[:4] == 'JUMP':
  261.             self.outEdges.add(inst[1])
  262.         
  263.         self.insts.append(inst)
  264.  
  265.     
  266.     def getInstructions(self):
  267.         return self.insts
  268.  
  269.     
  270.     def addInEdge(self, block):
  271.         self.inEdges.add(block)
  272.  
  273.     
  274.     def addOutEdge(self, block):
  275.         self.outEdges.add(block)
  276.  
  277.     
  278.     def addNext(self, block):
  279.         self.next.append(block)
  280.         if not len(self.next) == 1:
  281.             raise AssertionError, map(str, self.next)
  282.  
  283.     _uncond_transfer = ('RETURN_VALUE', 'RAISE_VARARGS', 'YIELD_VALUE', 'JUMP_ABSOLUTE', 'JUMP_FORWARD', 'CONTINUE_LOOP')
  284.     
  285.     def pruneNext(self):
  286.         """Remove bogus edge for unconditional transfers
  287.  
  288.         Each block has a next edge that accounts for implicit control
  289.         transfers, e.g. from a JUMP_IF_FALSE to the block that will be
  290.         executed if the test is true.
  291.  
  292.         These edges must remain for the current assembler code to
  293.         work. If they are removed, the dfs_postorder gets things in
  294.         weird orders.  However, they shouldn't be there for other
  295.         purposes, e.g. conversion to SSA form.  This method will
  296.         remove the next edge when it follows an unconditional control
  297.         transfer.
  298.         """
  299.         
  300.         try:
  301.             (op, arg) = self.insts[-1]
  302.         except (IndexError, ValueError):
  303.             return None
  304.  
  305.         if op in self._uncond_transfer:
  306.             self.next = []
  307.         
  308.  
  309.     
  310.     def get_children(self):
  311.         if self.next and self.next[0] in self.outEdges:
  312.             self.outEdges.remove(self.next[0])
  313.         
  314.         return self.outEdges.elements() + self.next
  315.  
  316.     
  317.     def getContainedGraphs(self):
  318.         '''Return all graphs contained within this block.
  319.  
  320.         For example, a MAKE_FUNCTION block will contain a reference to
  321.         the graph for the function body.
  322.         '''
  323.         contained = []
  324.         for inst in self.insts:
  325.             if len(inst) == 1:
  326.                 continue
  327.             
  328.             op = inst[1]
  329.             if hasattr(op, 'graph'):
  330.                 contained.append(op.graph)
  331.                 continue
  332.         
  333.         return contained
  334.  
  335.  
  336. RAW = 'RAW'
  337. FLAT = 'FLAT'
  338. CONV = 'CONV'
  339. DONE = 'DONE'
  340.  
  341. class PyFlowGraph(FlowGraph):
  342.     super_init = FlowGraph.__init__
  343.     
  344.     def __init__(self, name, filename, args = (), optimized = 0, klass = None):
  345.         self.super_init()
  346.         self.name = name
  347.         self.filename = filename
  348.         self.docstring = None
  349.         self.args = args
  350.         self.argcount = getArgCount(args)
  351.         self.klass = klass
  352.         if optimized:
  353.             self.flags = CO_OPTIMIZED | CO_NEWLOCALS
  354.         else:
  355.             self.flags = 0
  356.         self.consts = []
  357.         self.names = []
  358.         self.freevars = []
  359.         self.cellvars = []
  360.         self.closure = []
  361.         if not list(args):
  362.             pass
  363.         self.varnames = []
  364.         for i in range(len(self.varnames)):
  365.             var = self.varnames[i]
  366.             if isinstance(var, TupleArg):
  367.                 self.varnames[i] = var.getName()
  368.                 continue
  369.         
  370.         self.stage = RAW
  371.  
  372.     
  373.     def setDocstring(self, doc):
  374.         self.docstring = doc
  375.  
  376.     
  377.     def setFlag(self, flag):
  378.         self.flags = self.flags | flag
  379.         if flag == CO_VARARGS:
  380.             self.argcount = self.argcount - 1
  381.         
  382.  
  383.     
  384.     def checkFlag(self, flag):
  385.         if self.flags & flag:
  386.             return 1
  387.         
  388.  
  389.     
  390.     def setFreeVars(self, names):
  391.         self.freevars = list(names)
  392.  
  393.     
  394.     def setCellVars(self, names):
  395.         self.cellvars = names
  396.  
  397.     
  398.     def getCode(self):
  399.         '''Get a Python code object'''
  400.         if self.stage == RAW:
  401.             self.computeStackDepth()
  402.             self.flattenGraph()
  403.         
  404.         if self.stage == FLAT:
  405.             self.convertArgs()
  406.         
  407.         if self.stage == CONV:
  408.             self.makeByteCode()
  409.         
  410.         if self.stage == DONE:
  411.             return self.newCodeObject()
  412.         
  413.         raise RuntimeError, 'inconsistent PyFlowGraph state'
  414.  
  415.     
  416.     def dump(self, io = None):
  417.         if io:
  418.             save = sys.stdout
  419.             sys.stdout = io
  420.         
  421.         pc = 0
  422.         for t in self.insts:
  423.             opname = t[0]
  424.             if opname == 'SET_LINENO':
  425.                 print 
  426.             
  427.             if len(t) == 1:
  428.                 print '\t', '%3d' % pc, opname
  429.                 pc = pc + 1
  430.                 continue
  431.             print '\t', '%3d' % pc, opname, t[1]
  432.             pc = pc + 3
  433.         
  434.         if io:
  435.             sys.stdout = save
  436.         
  437.  
  438.     
  439.     def computeStackDepth(self):
  440.         '''Compute the max stack depth.
  441.  
  442.         Approach is to compute the stack effect of each basic block.
  443.         Then find the path through the code with the largest total
  444.         effect.
  445.         '''
  446.         depth = { }
  447.         exit = None
  448.         for b in self.getBlocks():
  449.             depth[b] = findDepth(b.getInstructions())
  450.         
  451.         seen = { }
  452.         
  453.         def max_depth(b, d):
  454.             if seen.has_key(b):
  455.                 return d
  456.             
  457.             seen[b] = 1
  458.             d = d + depth[b]
  459.             children = b.get_children()
  460.             if children:
  461.                 return []([ max_depth(c, d) for c in children ])
  462.             elif not b.label == 'exit':
  463.                 return max_depth(self.exit, d)
  464.             else:
  465.                 return d
  466.  
  467.         self.stacksize = max_depth(self.entry, 0)
  468.  
  469.     
  470.     def flattenGraph(self):
  471.         '''Arrange the blocks in order and resolve jumps'''
  472.         if not self.stage == RAW:
  473.             raise AssertionError
  474.         self.insts = insts = []
  475.         pc = 0
  476.         begin = { }
  477.         end = { }
  478.         for b in self.getBlocksInOrder():
  479.             begin[b] = pc
  480.             for inst in b.getInstructions():
  481.                 insts.append(inst)
  482.                 if len(inst) == 1:
  483.                     pc = pc + 1
  484.                     continue
  485.                 if inst[0] != 'SET_LINENO':
  486.                     pc = pc + 3
  487.                     continue
  488.             
  489.             end[b] = pc
  490.         
  491.         pc = 0
  492.         for i in range(len(insts)):
  493.             inst = insts[i]
  494.             if len(inst) == 1:
  495.                 pc = pc + 1
  496.             elif inst[0] != 'SET_LINENO':
  497.                 pc = pc + 3
  498.             
  499.             opname = inst[0]
  500.             if self.hasjrel.has_elt(opname):
  501.                 oparg = inst[1]
  502.                 offset = begin[oparg] - pc
  503.                 insts[i] = (opname, offset)
  504.                 continue
  505.             if self.hasjabs.has_elt(opname):
  506.                 insts[i] = (opname, begin[inst[1]])
  507.                 continue
  508.         
  509.         self.stage = FLAT
  510.  
  511.     hasjrel = misc.Set()
  512.     for i in dis.hasjrel:
  513.         hasjrel.add(dis.opname[i])
  514.     
  515.     hasjabs = misc.Set()
  516.     for i in dis.hasjabs:
  517.         hasjabs.add(dis.opname[i])
  518.     
  519.     
  520.     def convertArgs(self):
  521.         '''Convert arguments from symbolic to concrete form'''
  522.         if not self.stage == FLAT:
  523.             raise AssertionError
  524.         self.consts.insert(0, self.docstring)
  525.         self.sort_cellvars()
  526.         for i in range(len(self.insts)):
  527.             t = self.insts[i]
  528.             if len(t) == 2:
  529.                 (opname, oparg) = t
  530.                 conv = self._converters.get(opname, None)
  531.                 if conv:
  532.                     self.insts[i] = (opname, conv(self, oparg))
  533.                 
  534.             conv
  535.         
  536.         self.stage = CONV
  537.  
  538.     
  539.     def sort_cellvars(self):
  540.         '''Sort cellvars in the order of varnames and prune from freevars.
  541.         '''
  542.         cells = { }
  543.         for name in self.cellvars:
  544.             cells[name] = 1
  545.         
  546.         self.cellvars = _[1]
  547.         for name in self.cellvars:
  548.             del cells[name]
  549.         
  550.         self.cellvars = self.cellvars + cells.keys()
  551.         self.closure = self.cellvars + self.freevars
  552.  
  553.     
  554.     def _lookupName(self, name, list):
  555.         """Return index of name in list, appending if necessary
  556.  
  557.         This routine uses a list instead of a dictionary, because a
  558.         dictionary can't store two different keys if the keys have the
  559.         same value but different types, e.g. 2 and 2L.  The compiler
  560.         must treat these two separately, so it does an explicit type
  561.         comparison before comparing the values.
  562.         """
  563.         t = type(name)
  564.         for i in range(len(list)):
  565.             if t == type(list[i]) and list[i] == name:
  566.                 return i
  567.                 continue
  568.         
  569.         end = len(list)
  570.         list.append(name)
  571.         return end
  572.  
  573.     _converters = { }
  574.     
  575.     def _convert_LOAD_CONST(self, arg):
  576.         if hasattr(arg, 'getCode'):
  577.             arg = arg.getCode()
  578.         
  579.         return self._lookupName(arg, self.consts)
  580.  
  581.     
  582.     def _convert_LOAD_FAST(self, arg):
  583.         self._lookupName(arg, self.names)
  584.         return self._lookupName(arg, self.varnames)
  585.  
  586.     _convert_STORE_FAST = _convert_LOAD_FAST
  587.     _convert_DELETE_FAST = _convert_LOAD_FAST
  588.     
  589.     def _convert_LOAD_NAME(self, arg):
  590.         if self.klass is None:
  591.             self._lookupName(arg, self.varnames)
  592.         
  593.         return self._lookupName(arg, self.names)
  594.  
  595.     
  596.     def _convert_NAME(self, arg):
  597.         if self.klass is None:
  598.             self._lookupName(arg, self.varnames)
  599.         
  600.         return self._lookupName(arg, self.names)
  601.  
  602.     _convert_STORE_NAME = _convert_NAME
  603.     _convert_DELETE_NAME = _convert_NAME
  604.     _convert_IMPORT_NAME = _convert_NAME
  605.     _convert_IMPORT_FROM = _convert_NAME
  606.     _convert_STORE_ATTR = _convert_NAME
  607.     _convert_LOAD_ATTR = _convert_NAME
  608.     _convert_DELETE_ATTR = _convert_NAME
  609.     _convert_LOAD_GLOBAL = _convert_NAME
  610.     _convert_STORE_GLOBAL = _convert_NAME
  611.     _convert_DELETE_GLOBAL = _convert_NAME
  612.     
  613.     def _convert_DEREF(self, arg):
  614.         self._lookupName(arg, self.names)
  615.         self._lookupName(arg, self.varnames)
  616.         return self._lookupName(arg, self.closure)
  617.  
  618.     _convert_LOAD_DEREF = _convert_DEREF
  619.     _convert_STORE_DEREF = _convert_DEREF
  620.     
  621.     def _convert_LOAD_CLOSURE(self, arg):
  622.         self._lookupName(arg, self.varnames)
  623.         return self._lookupName(arg, self.closure)
  624.  
  625.     _cmp = list(dis.cmp_op)
  626.     
  627.     def _convert_COMPARE_OP(self, arg):
  628.         return self._cmp.index(arg)
  629.  
  630.     for name, obj in locals().items():
  631.         if name[:9] == '_convert_':
  632.             opname = name[9:]
  633.             _converters[opname] = obj
  634.             continue
  635.     
  636.     del name
  637.     del obj
  638.     del opname
  639.     
  640.     def makeByteCode(self):
  641.         if not self.stage == CONV:
  642.             raise AssertionError
  643.         self.lnotab = lnotab = LineAddrTable()
  644.         for t in self.insts:
  645.             opname = t[0]
  646.             if len(t) == 1:
  647.                 lnotab.addCode(self.opnum[opname])
  648.                 continue
  649.             oparg = t[1]
  650.             if opname == 'SET_LINENO':
  651.                 lnotab.nextLine(oparg)
  652.                 continue
  653.             
  654.             (hi, lo) = twobyte(oparg)
  655.             
  656.             try:
  657.                 lnotab.addCode(self.opnum[opname], lo, hi)
  658.             continue
  659.             except ValueError:
  660.                 print opname, oparg
  661.                 print self.opnum[opname], lo, hi
  662.                 raise 
  663.                 continue
  664.             
  665.  
  666.         
  667.         self.stage = DONE
  668.  
  669.     opnum = { }
  670.     for num in range(len(dis.opname)):
  671.         opnum[dis.opname[num]] = num
  672.     
  673.     del num
  674.     
  675.     def newCodeObject(self):
  676.         if not self.stage == DONE:
  677.             raise AssertionError
  678.         if self.flags & CO_NEWLOCALS == 0:
  679.             nlocals = 0
  680.         else:
  681.             nlocals = len(self.varnames)
  682.         argcount = self.argcount
  683.         if self.flags & CO_VARKEYWORDS:
  684.             argcount = argcount - 1
  685.         
  686.         return new.code(argcount, nlocals, self.stacksize, self.flags, self.lnotab.getCode(), self.getConsts(), tuple(self.names), tuple(self.varnames), self.filename, self.name, self.lnotab.firstline, self.lnotab.getTable(), tuple(self.freevars), tuple(self.cellvars))
  687.  
  688.     
  689.     def getConsts(self):
  690.         '''Return a tuple for the const slot of the code object
  691.  
  692.         Must convert references to code (MAKE_FUNCTION) to code
  693.         objects recursively.
  694.         '''
  695.         l = []
  696.         for elt in self.consts:
  697.             if isinstance(elt, PyFlowGraph):
  698.                 elt = elt.getCode()
  699.             
  700.             l.append(elt)
  701.         
  702.         return tuple(l)
  703.  
  704.  
  705.  
  706. def isJump(opname):
  707.     if opname[:4] == 'JUMP':
  708.         return 1
  709.     
  710.  
  711.  
  712. class TupleArg:
  713.     '''Helper for marking func defs with nested tuples in arglist'''
  714.     
  715.     def __init__(self, count, names):
  716.         self.count = count
  717.         self.names = names
  718.  
  719.     
  720.     def __repr__(self):
  721.         return 'TupleArg(%s, %s)' % (self.count, self.names)
  722.  
  723.     
  724.     def getName(self):
  725.         return '.%d' % self.count
  726.  
  727.  
  728.  
  729. def getArgCount(args):
  730.     argcount = len(args)
  731.     if args:
  732.         for arg in args:
  733.             if isinstance(arg, TupleArg):
  734.                 numNames = len(misc.flatten(arg.names))
  735.                 argcount = argcount - numNames
  736.                 continue
  737.         
  738.     
  739.     return argcount
  740.  
  741.  
  742. def twobyte(val):
  743.     '''Convert an int argument into high and low bytes'''
  744.     if not type(val) == types.IntType:
  745.         raise AssertionError
  746.     return divmod(val, 256)
  747.  
  748.  
  749. class LineAddrTable:
  750.     """lnotab
  751.  
  752.     This class builds the lnotab, which is documented in compile.c.
  753.     Here's a brief recap:
  754.  
  755.     For each SET_LINENO instruction after the first one, two bytes are
  756.     added to lnotab.  (In some cases, multiple two-byte entries are
  757.     added.)  The first byte is the distance in bytes between the
  758.     instruction for the last SET_LINENO and the current SET_LINENO.
  759.     The second byte is offset in line numbers.  If either offset is
  760.     greater than 255, multiple two-byte entries are added -- see
  761.     compile.c for the delicate details.
  762.     """
  763.     
  764.     def __init__(self):
  765.         self.code = []
  766.         self.codeOffset = 0
  767.         self.firstline = 0
  768.         self.lastline = 0
  769.         self.lastoff = 0
  770.         self.lnotab = []
  771.  
  772.     
  773.     def addCode(self, *args):
  774.         for arg in args:
  775.             self.code.append(chr(arg))
  776.         
  777.         self.codeOffset = self.codeOffset + len(args)
  778.  
  779.     
  780.     def nextLine(self, lineno):
  781.         if self.firstline == 0:
  782.             self.firstline = lineno
  783.             self.lastline = lineno
  784.         else:
  785.             addr = self.codeOffset - self.lastoff
  786.             line = lineno - self.lastline
  787.             if line >= 0:
  788.                 push = self.lnotab.append
  789.                 while addr > 255:
  790.                     push(255)
  791.                     push(0)
  792.                     addr -= 255
  793.                 while line > 255:
  794.                     push(addr)
  795.                     push(255)
  796.                     line -= 255
  797.                     addr = 0
  798.                 if addr > 0 or line > 0:
  799.                     push(addr)
  800.                     push(line)
  801.                 
  802.                 self.lastline = lineno
  803.                 self.lastoff = self.codeOffset
  804.             
  805.  
  806.     
  807.     def getCode(self):
  808.         return ''.join(self.code)
  809.  
  810.     
  811.     def getTable(self):
  812.         return ''.join(map(chr, self.lnotab))
  813.  
  814.  
  815.  
  816. class StackDepthTracker:
  817.     
  818.     def findDepth(self, insts, debug = 0):
  819.         depth = 0
  820.         maxDepth = 0
  821.         for i in insts:
  822.             opname = i[0]
  823.             if debug:
  824.                 print i,
  825.             
  826.             delta = self.effect.get(opname, None)
  827.             if delta is not None:
  828.                 depth = depth + delta
  829.             else:
  830.                 for pat, pat_delta in self.patterns:
  831.                     if opname[:len(pat)] == pat:
  832.                         delta = pat_delta
  833.                         depth = depth + delta
  834.                         break
  835.                         continue
  836.                 
  837.                 if delta is None:
  838.                     meth = getattr(self, opname, None)
  839.                     if meth is not None:
  840.                         depth = depth + meth(i[1])
  841.                     
  842.                 
  843.             if depth > maxDepth:
  844.                 maxDepth = depth
  845.             
  846.             if debug:
  847.                 print depth, maxDepth
  848.                 continue
  849.         
  850.         return maxDepth
  851.  
  852.     effect = {
  853.         'POP_TOP': -1,
  854.         'DUP_TOP': 1,
  855.         'SLICE+1': -1,
  856.         'SLICE+2': -1,
  857.         'SLICE+3': -2,
  858.         'STORE_SLICE+0': -1,
  859.         'STORE_SLICE+1': -2,
  860.         'STORE_SLICE+2': -2,
  861.         'STORE_SLICE+3': -3,
  862.         'DELETE_SLICE+0': -1,
  863.         'DELETE_SLICE+1': -2,
  864.         'DELETE_SLICE+2': -2,
  865.         'DELETE_SLICE+3': -3,
  866.         'STORE_SUBSCR': -3,
  867.         'DELETE_SUBSCR': -2,
  868.         'PRINT_ITEM': -1,
  869.         'RETURN_VALUE': -1,
  870.         'YIELD_VALUE': -1,
  871.         'EXEC_STMT': -3,
  872.         'BUILD_CLASS': -2,
  873.         'STORE_NAME': -1,
  874.         'STORE_ATTR': -2,
  875.         'DELETE_ATTR': -1,
  876.         'STORE_GLOBAL': -1,
  877.         'BUILD_MAP': 1,
  878.         'COMPARE_OP': -1,
  879.         'STORE_FAST': -1,
  880.         'IMPORT_STAR': -1,
  881.         'IMPORT_NAME': 0,
  882.         'IMPORT_FROM': 1,
  883.         'LOAD_ATTR': 0,
  884.         'SETUP_EXCEPT': 3,
  885.         'SETUP_FINALLY': 3,
  886.         'FOR_ITER': 1 }
  887.     patterns = [
  888.         ('BINARY_', -1),
  889.         ('LOAD_', 1)]
  890.     
  891.     def UNPACK_SEQUENCE(self, count):
  892.         return count - 1
  893.  
  894.     
  895.     def BUILD_TUPLE(self, count):
  896.         return -count + 1
  897.  
  898.     
  899.     def BUILD_LIST(self, count):
  900.         return -count + 1
  901.  
  902.     
  903.     def CALL_FUNCTION(self, argc):
  904.         (hi, lo) = divmod(argc, 256)
  905.         return -(lo + hi * 2)
  906.  
  907.     
  908.     def CALL_FUNCTION_VAR(self, argc):
  909.         return self.CALL_FUNCTION(argc) - 1
  910.  
  911.     
  912.     def CALL_FUNCTION_KW(self, argc):
  913.         return self.CALL_FUNCTION(argc) - 1
  914.  
  915.     
  916.     def CALL_FUNCTION_VAR_KW(self, argc):
  917.         return self.CALL_FUNCTION(argc) - 2
  918.  
  919.     
  920.     def MAKE_FUNCTION(self, argc):
  921.         return -argc
  922.  
  923.     
  924.     def MAKE_CLOSURE(self, argc):
  925.         return -argc
  926.  
  927.     
  928.     def BUILD_SLICE(self, argc):
  929.         if argc == 2:
  930.             return -1
  931.         elif argc == 3:
  932.             return -2
  933.         
  934.  
  935.     
  936.     def DUP_TOPX(self, argc):
  937.         return argc
  938.  
  939.  
  940. findDepth = StackDepthTracker().findDepth
  941.